﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace AMOOF {
    class TestMethods {

        //public static double maxErrorSeen = 0;
        //private static void testRecord(IntegrationRecord record) {
        //    IntegrationRecord matlab = record;
        //    PDF pdf = matlab.pdf;
        //    List<PDF> pdfs = new List<PDF>();
        //    List<double> scalings = new List<double>();
        //    scalings.Add(1);
        //    pdfs.Add(pdf);
        //    MultiplePDF pdf2 = new MultiplePDF(pdfs, scalings);
        //    IntegrationRecord integrator = Integrator.integrate(pdf2, record.xMean);

        //    for (int i = 1; i < 100; i++) {
        //        VarCtePair matlabPair = matlab.getPercentile(i);
        //        VarCtePair integratorPair = integrator.getPercentile(i);
        //        Boolean valid = (matlabPair.leftCTEFound && integratorPair.leftCTEFound);
        //        if (!valid) {
        //            continue;
        //        }
        //        double matlabCTE = matlabPair.leftCte;
        //        double integratorCTE = integratorPair.leftCte;

        //        double matlabRightCTE = matlabPair.rightCte;
        //        double integratorRightCTE = integratorPair.rightCte;

        //        double matlabPercentile = matlabPair.leftPercentile;
        //        double integratorPercentile = integratorPair.leftPercentile;

        //        double matlabVAR = matlabPair.var;
        //        double integratorVAR = integratorPair.var;

        //        string result = "Matlab".PadRight(25) + "Integrator\n" +
        //            "Area at this point:".PadRight(25) + integratorPair.integral +
        //            "\nPercentile:".PadRight(25) + matlabPercentile;
        //        if (matlabVAR != 0) {
        //            double varError = Math.Abs(matlabVAR - integratorVAR) / matlabVAR;
        //            maxErrorSeen = Math.Max(varError, maxErrorSeen);
        //            result += "\nVARError:".PadRight(25) + varError;
        //        }
        //        if (matlabCTE != 0) {
        //            double cteError = Math.Abs(matlabCTE - integratorCTE) / matlabCTE;
        //            maxErrorSeen = Math.Max(cteError, maxErrorSeen);
        //            result += "\nLCTEError:".PadRight(25) + cteError;
        //        }
        //        if (matlabRightCTE != 0) {
        //            double rcteError = Math.Abs(matlabRightCTE - integratorRightCTE) / matlabRightCTE;
        //            maxErrorSeen = Math.Max(rcteError, maxErrorSeen);
        //            result += "\nRCTEError:".PadRight(25) + rcteError;
        //        }
        //        result += "\nEstimated Error:".PadRight(25) + Math.Abs(integratorPair.integral - (double)i / 100) / integratorPair.integral +
        //        "\n\n";
        //        Console.WriteLine(result);
        //    }
        //    //string s = "";
        //    //Console.WriteLine(s);
        //    Console.WriteLine(pdf.ToString());
        //    // Console.ReadLine();
        //}

        //static List<List<PDF>> pdfPairs;
        //static List<MultiplePDF> multiplePDFs;

        //private static string displayIntegrationRecord(IntegrationRecord periRecord) {
        //    String str = "\r\n\r\n";
        //    str += "==================================== "
        //        + periRecord.pdf.name + "".PadRight(5)
        //        + " Area: " + periRecord.totalArea;

        //    str += "\r\n" + periRecord.boundsString;
        //    str += ((MultiplePDF)periRecord.pdf).getGreeksString();
        //    //for (int i = 1; i < 100; i++) {
        //    //    VarCtePair periVAR = periRecord.getPercentile(i);
        //    //    if (periVAR.leftCTEFound) {
        //    //        str += "\r\n";
        //    //        str += format(periVAR.integral, 10) + "".PadRight(5)
        //    //            + format(periVAR.leftCte, 10) + "".PadRight(5)
        //    //            + format(periVAR.var, 10) + "".PadRight(5)
        //    //            + format(periVAR.rightCte, 10) + "".PadRight(5);
        //    //    }
        //    //}

        //    //for (int i = 1; i < 100; i++) {
        //    //    VarCtePair periVAR = periRecord.getPercentile(i);
        //    //    VarCtePair AMOOFVAR = AMOOFRecord.getPercentile(i);
        //    //    double errorArea = Math.Abs(periVAR.integral - AMOOFVAR.integral) / periVAR.integral;
        //    //    double errorLCTE = Math.Abs(periVAR.leftCte - AMOOFVAR.leftCte) / periVAR.leftCte;
        //    //    double errorVAR = Math.Abs(periVAR.var - AMOOFVAR.var) / periVAR.var;
        //    //    double errorRightCTE = Math.Abs(periVAR.rightCte - AMOOFVAR.rightCte) / periVAR.rightCte;
        //    //    double maxError = Math.Max(errorArea, errorLCTE);
        //    //    maxError = Math.Max(maxError, errorVAR);
        //    //    maxError = Math.Max(maxError, errorRightCTE);
        //    //    if (periVAR.leftCTEFound) {
        //    //        str += "\r\n";
        //    //        str += format(periVAR.integral, 10) + "".PadRight(5)
        //    //            + format(periVAR.leftCte, 10) + "".PadRight(5)
        //    //            + format(periVAR.var, 10) + "".PadRight(5)
        //    //            + format(periVAR.rightCte, 10) + "".PadRight(5)
        //    //            + format(maxError, 10);
        //    //        str += "\r\n";
        //    //        str += format(AMOOFVAR.integral, 10) + "".PadRight(5)
        //    //            + format(AMOOFVAR.leftCte, 10) + "".PadRight(5)
        //    //            + format(AMOOFVAR.var, 10) + "".PadRight(5)
        //    //            + format(AMOOFVAR.rightCte, 10);
        //    //    }
        //    //}
        //    return str;
        //}

        //static int passed = 0;
        //static int failed = 0;
        //private static string testPDFPeri(MultiplePDF pdf, double low, double high, double iterations) {
        //    String resultString = "";
        //    for (int i = 0; i < iterations; i++) {
        //        IntegrationRecord recordPeri = Integrator.integratePeri(pdf);
        //        resultString += displayIntegrationRecord(recordPeri);
        //        if (Math.Abs(recordPeri.totalArea - 1.00000) < .000001) {
        //            passed++;
        //        }
        //        else {
        //            failed++;
        //        }
        //    }
        //    return resultString;
        //}

        //public static void testPeriInterface(string filename, int numTests, double greekLow, double greekHigh, Boolean mixed) {
        //    String resultString = "Range of Greeks:".PadRight(5) + "[" + greekLow + "," + greekHigh + "]";
        //    List<MultiplePDF> pdfs = new List<MultiplePDF>();

        //    int pdfsPerUnit = mixed ? 2 : 1;
        //    initializePDFs(pdfsPerUnit, greekLow, greekHigh);
        //    for (int i = 0; i < multiplePDFs.Count; i++) {
        //        try {
        //            MultiplePDF pdf = multiplePDFs.ElementAt(i);
        //            resultString += testPDFPeri(pdf, greekLow, greekHigh, numTests);
        //        }
        //        catch (Exception e) { Program.log(e.Message + "\r\n" + e.StackTrace); }
        //    }
        //    IOProcessor.writeToFile(filename, resultString);
        //}

        //private static string compareRecords(IntegrationRecord periRecord, IntegrationRecord AMOOFRecord) {
        //    String str = "\r\n\r\n";
        //    str += "==========================";
        //    str += periRecord.pdf.name;
        //    str += "\r\n" + ((MultiplePDF)periRecord.pdf).getGreeksString();
        //    str += "\r\n\r\nTotal Area Peri: ".PadRight(10) + periRecord.totalArea;
        //    str += "\r\nTotal Area AMOOF: ".PadRight(10) + AMOOFRecord.totalArea;
        //    str += "\r\n";
        //    for (int i = 1; i < 100; i++) {
        //        VarCtePair periVAR = periRecord.getPercentile(i);
        //        VarCtePair AMOOFVAR = AMOOFRecord.getPercentile(i);
        //        double errorArea = Math.Abs(periVAR.integral - AMOOFVAR.integral) / periVAR.integral;
        //        double errorLCTE = Math.Abs(periVAR.leftCte - AMOOFVAR.leftCte) / periVAR.leftCte;
        //        double errorVAR = Math.Abs(periVAR.var - AMOOFVAR.var) / periVAR.var;
        //        double errorRightCTE = Math.Abs(periVAR.rightCte - AMOOFVAR.rightCte) / periVAR.rightCte;
        //        double maxError = Math.Max(errorArea, errorLCTE);
        //        maxError = Math.Max(maxError, errorVAR);
        //        maxError = Math.Max(maxError, errorRightCTE);
        //        if (periVAR.leftCTEFound) {
        //            str += "\r\n";
        //            str += format(periVAR.integral, 10) + "".PadRight(5)
        //                + format(periVAR.leftCte, 10) + "".PadRight(5)
        //                + format(periVAR.var, 10) + "".PadRight(5)
        //                + format(periVAR.rightCte, 10) + "".PadRight(5)
        //                + format(maxError, 10);
        //            str += "\r\n";
        //            str += format(AMOOFVAR.integral, 10) + "".PadRight(5)
        //                + format(AMOOFVAR.leftCte, 10) + "".PadRight(5)
        //                + format(AMOOFVAR.var, 10) + "".PadRight(5)
        //                + format(AMOOFVAR.rightCte, 10);
        //        }
        //    }
        //    return str;
        //}

        //static string format(double number, int decimalPlaces) {
        //    String temp = "{0:0.";
        //    for (int i = 0; i < decimalPlaces; i++) {
        //        temp += "0";
        //    }
        //    temp += "}";
        //    return String.Format(temp, number);
        //}

        //public static void testSEP_20ScientificNotation() {
        //    double a = 1.0e+12;
        //    double b = Convert.ToDouble("1.0e+12");

        //}

        //public static void testSEP_7() {
        //    initializePDFs(1, 1, 10);
        //    string result = "======TEST PDF INTEGRATION======";
        //    foreach (MultiplePDF pdf in multiplePDFs) {
        //        IntegrationRecord record = Integrator.integratePeri(pdf);
        //        // IntegrationRecord record = Integrator.integrate(pdf,100);
        //        Console.WriteLine(record.totalArea);
        //        result += "\r\n";
        //        result += record.pdf.name;
        //        result += "".PadRight(20) + record.totalArea; 
        //    }
        //    IOProcessor.writeToFile("PDF_INTEGRATION_SEP7", result);
        //}

        //static MultiplePDF buildMultiPDF(List<PDF> pdfs, double low, double high) {
        //    double width = high - low;
        //    List<double> scalings = new List<double>();
        //    pdfs.ForEach(s => {
        //        scalings.Add(1.0 / pdfs.Count);
        //        List<PDF.Variable> variables = s.greeks;
        //        foreach (PDF.Variable variable in variables) {
        //            variable.value = random.NextDouble() * width + low;
        //        }
        //    });
        //    MultiplePDF mPDF = new MultiplePDF(pdfs, scalings);
        //    return mPDF;
        //}

        //static void initializePDFs(int numPDFs, double low, double high) {
        //    pdfPairs = new List<List<PDF>>();
        //    multiplePDFs = new List<MultiplePDF>();
        //    List<PDF> pair;

        //    //// beta
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Beta());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// burr
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Burr());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// exponential
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Exponential());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// gamma
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Gamma());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// generalized beta
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new GeneralizedBeta());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// generalized pareto
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new GeneralizedPareto());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse burr
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseBurr());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse exponential
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseExponential());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse gamma
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseGamma());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse gaussian
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseGaussian());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse paralogistic
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseParalogistic());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse pareto
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InversePareto());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse transformed gamma
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseTransformedGamma());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// inverse weibull
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new InverseWeibull());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// loglogistic
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Loglogistic());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    // lognormal
        //    pair = new List<PDF>();
        //    for (int i = 0; i < numPDFs; i++) {
        //        pair.Add(new Lognormal());
        //    }
        //    pdfPairs.Add(pair);
        //    multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// paralogistic
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Paralogistic());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// pareto
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Pareto());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// single parameter pareto
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new SingleParameterPareto());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// transformed beta
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new TransformedBeta());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// transformed gamma
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new TransformedGamma());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));

        //    //// weibull
        //    //pair = new List<PDF>();
        //    //for (int i = 0; i < numPDFs; i++) {
        //    //    pair.Add(new Weibull());
        //    //}
        //    //pdfPairs.Add(pair);
        //    //multiplePDFs.Add(buildMultiPDF(pair, low, high));  
        //}

        //static Random random = new Random();

        //public static string integrateTestRandomParameters
        //    (double low, double high, int numPDFs, string outputFileName) {
        //    double minGreek = low;
        //    double maxGreek = high;
        //    double width = maxGreek - minGreek;
        //    initializePDFs(numPDFs, low, high);
        //    int passed = 0;
        //    int failed = 0;
        //    string output = "";
        //    string exceptions = "";
        //    string areasFound = "";
        //    int desiredTests = 1;
        //    int tests = 0;
        //    while (tests < desiredTests) {
        //        tests++;
        //        Console.WriteLine("Test: " + tests);
        //        foreach (List<PDF> pair in pdfPairs) {
        //            String localString = "";
        //            localString += "\n=========================" + "\n" + pair.ElementAt(0).name;
        //            Console.WriteLine(localString);

        //            try {
        //                List<double> scalings = new List<double>();

        //                pair.ForEach(s => {
        //                    scalings.Add(1.0 / pair.Count);
        //                    List<PDF.Variable> variables = s.greeks;
        //                    foreach (PDF.Variable variable in variables) {
        //                        variable.value = random.NextDouble() * width + minGreek;
        //                        localString += "\n" + variable.type + "".PadRight(5) + variable.value;
        //                    }
        //                }
        //                );

        //                MultiplePDF mPDF = new MultiplePDF(pair, scalings);
        //                IntegrationRecord integrator = Integrator.integrate(mPDF, 1);
        //                // localString += "\n" + integrator.bounds.getString() + "\n";
        //                List<Bounds> listBounds = mPDF.getBounds();
        //                foreach (Bounds b in listBounds) {
        //                    localString += "\n" + b;
        //                }

        //                Console.WriteLine(output);
        //                Console.Clear();
        //                //Console.WriteLine(integrator.getPercentile(1));
        //                //Console.WriteLine(integrator.getPercentile(99));
        //                passed++;
        //                areasFound += integrator.totalArea + "\t" + integrator.pdf.name + "\n";
        //                Console.WriteLine(integrator.totalArea);
        //                //// Console.WriteLine(integrator.bounds.getString());
        //                //if (validIntegration(integrator)) {
        //                //    passed += 1;
        //                //} else {
        //                //    localString += "\n" + "Failed to find all VARs";
        //                //    output += localString;
        //                //    failed++;
        //                //}
        //            }
        //            catch (Exception e) {
        //                Program.log(e.Message + "\r\n" + e.StackTrace);
        //                failed++;
        //                localString += "\n" + e.Message;
        //                output += localString;
        //            }
        //        }
        //    }
        //    output = "\n\n==============Random Variable Test\n"
        //        + "\nParameter Range: " + "[" + low + " , " + high + "]"
        //        + "\nPassed:".PadRight(10) + passed
        //        + "\nFailed:".PadRight(10) + failed
        //        + "\n" + areasFound
        //        + "\nFailures: " + output;

        //    Console.WriteLine(output);
        //    return output;
        //}

        //public static void testStatistics() {
        //    List<string> paths = new List<string>();
        //    paths.Add(@"F:\Source\OnlineRepository\AMOOFWinter\AMOOFWinter\StatisticsFolder\10000DataSet2.csv");
        //    //paths.Add(@"F:\Source\OnlineRepository\AMOOFWinter\AMOOFWinter\StatisticsFolder\Distance50.csv");
        //    //paths.Add(@"F:\Source\OnlineRepository\AMOOFWinter\AMOOFWinter\StatisticsFolder\LN53.csv");
        //    //paths.Add(@"F:\Source\OnlineRepository\AMOOFWinter\AMOOFWinter\StatisticsFolder\LN83.csv");

        //    foreach (string path in paths) {
        //        DataPoint[] dataPoints = IOProcessor.loadDataPoints(path);

        //        List<Tuple<double, int>> freqList = new List<Tuple<double, int>>();
        //        double[] freqList2 = new double[dataPoints.Length];

        //        for (int i = 0; i < dataPoints.Length; i++) {
        //            DataPoint thisPoint = dataPoints.ElementAt(i);
        //            Tuple<double, int> temp = new Tuple<double, int>(thisPoint.x, (int)thisPoint.y);
        //            double x = thisPoint.x;
        //            double y = thisPoint.y;
        //            freqList.Add(temp);
        //            freqList2[i] = x;
        //        }

        //        Statistics statsClass = new Statistics(freqList);
        //        statsClass.getAllStatistics();
        //        Console.WriteLine(statsClass);
        //    }
        //}
    }
}
